package tm;

import java.util.Objects;

/**
 * @author haoly
 * @title TMRule
 * @date 2025/4/23 13:36
 * @description 图灵机规则类
 */
public class TMRule<T> {
    private final T state;

    private final Character character;

    private final T nextState;

    private final Character writeCharacter;

    private EnumDirection direction;

    public TMRule(T state, Character character, T nextState, Character writeCharacter, EnumDirection direction) {
        this.state = state;
        this.character = character;
        this.nextState = nextState;
        this.writeCharacter = writeCharacter;
        this.direction = direction;
    }

    public T getState() {
        return state;
    }

    public Character getCharacter() {
        return character;
    }

    public T getNextState() {
        return nextState;
    }

    public Character getWriteCharacter() {
        return writeCharacter;
    }

    public EnumDirection getDirection() {
        return direction;
    }

    public Boolean appliesTo(TMConfiguration<T> configuration){
        return Objects.equals(state, configuration.getState())
                && Objects.equals(character, configuration.getTape().getMiddle());
    }

    public TMConfiguration<T> follow(TMConfiguration<T> configuration){
        Tape nextTap = nextTape(configuration);

        return new TMConfiguration<>(nextState, nextTap);
    }

    public Tape nextTape(TMConfiguration<T> configuration) {
        Tape writtenTape = configuration.getTape().write(writeCharacter);
        switch (direction){
            case LEFT:
                writtenTape = writtenTape.moveHeadLeft();
                break;
            case RIGHT:
                writtenTape = writtenTape.moveHeadRight();
                break;
        }
        return writtenTape;
    }


    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("#<struct TMRule ");
        sb.append("state=").append(state).append(",");
        sb.append("character=").append(character).append(",");
        sb.append("nextState=").append(nextState).append(",");
        sb.append("writeCharacter=").append(writeCharacter).append(",");
        sb.append("direction=").append(direction);
        sb.append(">");

        return sb.toString();
    }
}
